from Location import Location
from Sugarscape import *
import random
import time

class Agent(object):

    def __init__(self, xloc, yloc, vision, sugar_reserve, metabolism, sugarscape, gender):
        self.vision = self.make_vision(vision)
        #self.vision = vision
        self.sugar_reserve = random.normalvariate(sugar_reserve,1)
        self.sugarscape = sugarscape
        self.location = self.sugarscape.get_location(xloc, yloc)
        self.metabolism = round(random.normalvariate(metabolism-1,1) + 1,2)
        if self.metabolism <= 0: 
            self.metabolism = .1
        self.location.set_has_agent(True)
        self.gender = gender
        self.age = 0

    def make_vision(self, vision):
        '''generates random vision for agents centered around 
        the vision variable'''
        vision = int(round(random.normalvariate(vision,2)))
        return vision if vision > 0 else 1

    def set_sugar_reserve(self, amount):
        self.sugar_reserve = amount

    def get_vision(self):
        return self.vision

    def get_metabolism(self):
        return self.metabolism

    def get_age(self):
        return self.age

    def get_gender(self):
        return self.gender

    def get_location(self):
        '''find the current location object of the agent'''
        return self.location

    def get_sugar_reserve(self):
        return self.sugar_reserve

    def observe(self):
        '''look around for best next move. returns location object.'''
        nearby_locs = self.sugarscape.get_nearby_locations(self.vision, self.location)
        max_sugar = 0
        best_loc = [self.location]
        for location in nearby_locs:
            if location.sugar_amt > max_sugar and not location.get_has_agent():
                max_sugar = location.sugar_amt
                best_loc = [location]
            elif location.sugar_amt == max_sugar and not location.get_has_agent():
                best_loc.append(location)
        return random.choice(best_loc)

    def nextstep(self):
        '''figure out the next move and then move there, then handle sugar'''
        self.age += 1
        if self.sugarscape.reproduction and self.get_age() > 100 and random.choice(range(69)) == 0:
            self.die(self.location)
            print "died of old age :("
            return
        self.walk(self.observe())
        self.sugar_reserve += self.location.sugar_amt
        self.location.set_sugar_amt(self.leave_behind())
        self.sugar_reserve -= self.metabolism
        if self.sugar_reserve <= 0 and self.sugarscape.timestamp > 1:
            self.die(self.location)
        self.reproduce()

    def walk(self, location):
        '''physically move to the next spot'''
        self.location.set_has_agent(False)
        self.location = location
        self.location.set_has_agent(True)
        return True

    def die(self, location):
        self.sugarscape.remove_agent(self)
        self.location.set_has_agent(False)
        #print "I'm dead!"
        return True


    def reproduce(self):
        if self.sugarscape.reproduction:
            for agent in self.sugarscape.get_nearby_agents(self.location):
                if self.fertility_check(agent):
                    self.make_baby(agent)
        return False

    def fertility_check(self, other):
        #TODO: make a value for minimum sugar reserve
        #give a proportion for reproduction
        if self.get_age() > 50 and other.get_age() > 50 and random.choice([True, False, False]) and self.get_gender() != other.get_gender():
            return True
        return False

    def make_baby(self, parent):
        #print parent, self
        x = self.location.x + random.choice([-1, 1])
        y = self.location.y + random.choice([-1, 1])
        if not self.sugarscape.get_location(x, y).get_has_agent():    
            gender = random.choice(['male', 'female'])
            sugar_amt = self.get_sugar_reserve()*.25 + parent.get_sugar_reserve()*.25
            self.set_sugar_reserve(self.get_sugar_reserve()*.75)
            parent.set_sugar_reserve(parent.get_sugar_reserve()*.75)
            agent = Agent(x, y, int((self.get_vision() + parent.get_vision())/2), sugar_amt, (self.get_metabolism() + parent.get_metabolism())/2, self.sugarscape, gender)
            self.sugarscape.agents.append(agent)
            self.sugarscape.num_agents += 1
            print "makin' baby!"

    def leave_behind(self):
        if self.sugar_reserve < 0:
            return 0
        else:
            return (self.sugar_reserve* len(self.sugarscape.agents)/float(self.sugarscape.total_wealth))**1.1 / 5

    def __str__(self):
        return "agent: sugar_reserve: %g, location: %d, %d, vision: %d, metabolism: %d, gender: %s" %(self.sugar_reserve, self.location.x, self.location.y, self.vision, self.metabolism, self.gender)

if __name__=="__main__":
    start = time.clock()
    sug = Sugarscape()
    a = Agent(2, 2, 2, 2, 2, sug)

    print a.vision
    sug.get_location(2,3).sugar_amt = 10
    sug.get_location(2,4).sugar_amt = 10
    print a.observe()
    elapsed = (time.clock() - start)
    print elapsed
